(function(angular) {
	'use strict';

	angular.module("fs.waf").provider('gridService', gridServiceProvider);
	gridServiceProvider.$inject = [ 'SYS_PARAMS', 'uiGridConstants' ];
	function gridServiceProvider(SYS_PARAMS, uiGridConstants) {
		var provider = this, supportMultiPageSelectAll = false;
		provider.innerGridOptions = {
			headerRowHeight : 40,
			rowHeight : 36,
			minRowsToShow : 5,
			gridFooterHeight : 22,
			enableGridMenu : false,
			showGridFooter : false,
			showColumnFooter : false,
			enableSorting : false,
			useExternalSorting : true,
			enableFiltering : false,
			enableColumnMoving : true,
			enableColumnMenus : false,
			enableHorizontalScrollbar : uiGridConstants.scrollbars.WHEN_NEEDED,
			enableVerticalScrollbar : uiGridConstants.scrollbars.NEVER,
			virtualizationThreshold: 100,
			columnVirtualizationThreshold: 30,

			enablePagination : false,
			enablePaginationControls : false,
			useExternalPagination : false,
			useCustomPagination : false,
			paginationPageSizes : [ 10, 20, 30, 40, 50, 100 ],
			paginationPageSize : 10,
			paginationCurrentPage : 1,

			enableRowSelection : false,
			multiSelect : false,
			multiPageSelect : false,
			noUnselect : false,
			modifierKeysToMultiSelect : false,
			enableRowHeaderSelection : false,
			enableFullRowSelection : false,
			enableSelectAll : true,
			
			enableOperation : false,
			enableOperationRemoveSelected : false,
			enableEolOperation : false,
			
			enableColumnResizing : true,
			enableAutoResize : 1,
			
			treeRowHeaderAlwaysVisible: false,
			enableGrouping : false,
			groupingShowCounts : false,
			//groupingNullLabel : ,
			enableGroupHeaderSelection : false,
			isRowSelectable : function(row) {
				if (row.groupHeader) {
					return false;
				}
				return true;
			}
		};

		provider.defaultGridOptions = {
			headerRowHeight : 40,
			rowHeight : 36,
			minRowsToShow : 5,
			enableGridMenu : false,
			showGridFooter : false,
			showColumnFooter : false,
			enableSorting : true,
			gridFooterHeight : 22,
			useExternalSorting : true,
			enableFiltering : false,
			enableColumnMoving : true,
			enableColumnMenus : false,
			enableHorizontalScrollbar : uiGridConstants.scrollbars.WHEN_NEEDED,
			enableVerticalScrollbar : uiGridConstants.scrollbars.NEVER,
			virtualizationThreshold: 100,
			columnVirtualizationThreshold: 30,

			enablePagination : true,
			enablePaginationControls : true,
			useExternalPagination : true,
			useCustomPagination : false,
			paginationPageSizes : [ 10, 20, 30, 40, 50, 100 ],
			paginationPageSize : 10,
			paginationCurrentPage : 1,

			enableRowSelection : true,
			multiSelect : false,
			multiPageSelect : false,
			noUnselect : false,
			modifierKeysToMultiSelect : false,
			enableRowHeaderSelection : true,
			enableFullRowSelection : true,
			enableSelectAll : true,
			
			enableOperation : false,
			enableOperationRemoveSelected : false,
			enableEolOperation : false,
			
			enableColumnResizing : true,
			enableAutoResize : 1,
			
			treeRowHeaderAlwaysVisible: false,
			enableGrouping : false,
			groupingShowCounts : false,
			//groupingNullLabel : ,
			enableGroupHeaderSelection : false,
			isRowSelectable : function(row) {
				if (row.groupHeader) {
					return false;
				}
				return true;
			},
			pageNoKeydown : function(e) {
				var evt = window.event || e;
			    var keyCode = evt.which ? evt.which : evt.keyCode;
			    //enter key Code
			    if(keyCode == 13) {
			    	if(evt.preventDefault) evt.preventDefault();
			        if(evt.stopPropagation) evt.stopPropagation();
			        evt.returnValue = false;
			    }
			}

		// exporterMenuCsv : false,
		// exporterMenuPdf : false,
		// exporterSuppressMenu : false,
		// exporterMenuAllData : false,
		// exporterMenuVisibleData : true,
		// exporterMenuSelectedData : true,
		// exporterMenuLabel : 'Export',
		// exporterSuppressColumns : [],
		// exporterCsvColumnSeparator : ',',
		// exporterFieldCallback : function(grid, row, col, value) {
		// return value;
		// },
		// exporterHeaderFilter : function(displayName) {
		// return displayName;
		// },
		// exporterHeaderFilterUseName : true,
		// exporterOlderExcelCompatibility : false,
		// exporterCsvFilename : 'download.csv',
		// exporterPdfFilename : 'download.pdf'
		};

		provider.fsGridTemplate = '<div fs-grid ng-model=\"row.entity\" fs-ui-grid=\"grid\" fs-ui-grid-row=\"row\" fs-ui-grid-col=\"col\" fs-grid-config=\"col.colDef\" fs-verify-model="row.grid.options.verifyData" fs-validator-config=\"col.colDef.validatorConfig\"></div>';
		this.$get = gridServiceGet;
		gridServiceGet.$inject = [ '$rootScope', '$translate', '$q', '$timeout', 'uiGridConstants', 'i18nService', 'loggerFactory', 'storageService', 'modalService' ];
		function gridServiceGet($rootScope, $translate, $q, $timeout, uiGridConstants, i18nService, loggerFactory, storageService, modalService) {
			var log = loggerFactory.getLogger("gridService");
			function removeRows($scope, selectedRows, apiBoundName) {
				if (!selectedRows || selectedRows.length == 0) {
					return;
				}
				apiBoundName = apiBoundName || 'gridApi';
				var allRows = angular.isString($scope[apiBoundName].grid.options.data) ? $scope
						.$eval($scope[apiBoundName].grid.options.data) : $scope[apiBoundName].grid.options.data;
				angular.forEach(selectedRows, function(row) {
					$scope[apiBoundName].selection.unSelectRow(row);
				});
				angular.forEach(selectedRows, function(selectedRow) {
					removeItem(allRows, selectedRow);
				});
			}
			function removeSelectedRows($scope, apiBoundName) {
				apiBoundName = apiBoundName || 'gridApi';
				var selectedRows = $scope[apiBoundName].selection.getSelectedRows();
				removeRows($scope, selectedRows, apiBoundName);
			}
			function removeItem(items, item) {
				angular.forEach(items, function(row, index) {
					if (row.$$hashKey == item.$$hashKey) {
						items.splice(index, 1);
					}
				});
			}
			function createInnerGridOptions($scope, tableConfig, rowSelectionChanged, sortChanged, apiBoundName) {
				var options = angular.copy(provider.innerGridOptions);
				var tableSetting = storageService.getTableSetting($scope.$state.current.name + ':' + tableConfig.name);
				options.name = tableConfig.name;
				apiBoundName = apiBoundName || tableConfig.apiBoundName || 'gridApi';
				// i18nService.setCurrentLang($rootScope.I18N.language);
				i18nService.setCurrentLang('en');
				// options.gridMenuTitleFilter = $translate;
				prepareColumnDefs($scope, tableConfig, options, tableSetting);
				options.columnDefs = tableConfig.columnDefs || [];
				if (options.enableVerticalScrollbar == uiGridConstants.scrollbars.NEVER && options.columnDefs.length > 0) {
					options.columnDefs[options.columnDefs.length - 1].pinnedRight = true;
				}
				options.onRegisterApi = function(gridApi) {
					$scope[apiBoundName] = options['gridApi'] = gridApi;
					if (gridApi.rowEdit) {
						gridApi.rowEdit.on.saveRow($scope, function(rowEntity) {
							var defered = $q.defer();
							$scope[apiBoundName].rowEdit.setSavePromise(rowEntity, defered.promise);
							defered.resolve();
							return defered.promise;
						});
					}
					if (gridApi.selection) {
						gridApi.selection.on.rowSelectionChanged($scope, function(row, event) {
							if (angular.isFunction(rowSelectionChanged)) {
								rowSelectionChanged(row, row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows());
							}
						});
						gridApi.selection.on.rowSelectionChangedBatch($scope, function(rows, event) {
							if (angular.isFunction(rowSelectionChanged)) {
								angular.forEach(rows, function(row) {
									rowSelectionChanged(row, row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows());
								});
							}
						});
					}
					gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
						var sorts = [];
						angular.forEach(sortColumns, function(sortColumn, key) {
							sorts.push({
								sortBy : sortColumn.colDef.sortBy,
								direction : sortColumn.sort.direction
							});
						});
						(sortChanged || angular.noop)(sorts);
					});
					gridApi.grid.registerDataChangeCallback(function() {
			            if(gridApi.grid.treeBase && (gridApi.grid.treeBase.tree instanceof Array) && tableConfig.expandAll){
			                gridApi.treeBase.expandAllRows();
			            }
			        });
					gridApi.grid.registerDataChangeCallback(function(grid) {
						if (gridApi.grid._selectedRows && gridApi.grid._selectedRows.length > 0) {
							if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
								options.defaultSearchCriteria.selectAll = gridApi.grid.selection.selectAll;
							}
							angular.forEach(grid.rows, function(row) {
								if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
									gridApi.selection.selectRow(row.entity);
								} else if (containRow(gridApi.grid, gridApi.grid._selectedRows, row.entity)) {
									gridApi.selection.selectRow(row.entity);
								}
							});
						}
						if (grid.options.selectAll) {
							angular.forEach(grid.rows, function(row) {
								gridApi.selection.selectRow(row.entity);
							});
						}
						
			        }, [uiGridConstants.dataChange.ROW]);
					if (gridApi.colMovable && gridApi.colMovable.raise) {
						gridApi.colMovable.raise.columnPositionChanged = function (colDef, originalPosition, newPosition) {
							var order = [];
							if(gridApi.grid.moveColumns && gridApi.grid.moveColumns.orderCache){
								angular.forEach(gridApi.grid.moveColumns.orderCache, function(orderCache){
									order.push(orderCache.colDef.field);
								});
							}
							storageService.saveTableSetting($scope.$state.current.name + ':' + gridApi.grid.options.name, {
								order : order,
							});
						};
					}
					$scope.$on('ADD_ROWS', function($event, rows) {
						$event.preventDefault();
						$event.stopPropagation();
					});
					$scope.$on('REMOVE_ROWS', function($event, rows) {
						$event.preventDefault();
						$event.stopPropagation();
					});
				};
				if (tableConfig.hasOwnProperty('enableRowHeaderSelection')) {
					options.enableRowHeaderSelection = tableConfig.enableRowHeaderSelection;
				}
				options.enableOperation = tableConfig.enableOperation;
				options.enableOperationRemoveSelected = tableConfig.enableOperationRemoveSelected;
				options.addRow = tableConfig.addRow;
				options.removeSelectedRows = tableConfig.removeSelectedRows;
				options.removeAllRows = tableConfig.removeAllRows;
				options.viewRow = tableConfig.viewRow;
				options.editRow = tableConfig.editRow;
				options.addSubRow = tableConfig.addSubRow;
				options.removeRow = tableConfig.removeRow;
				options.data = tableConfig.model;
				options.verifyData = tableConfig.verifyModel;
				options.validatorConfig = tableConfig.validatorConfig;
				options.moreProcess = tableConfig.moreProcess;
				options.moreProcessByEol = tableConfig.moreProcessByEol;
				if (tableConfig.hasOwnProperty('isRowSelectable')) {
					if (angular.isString(tableConfig.isRowSelectable)) {
						options.isRowSelectable = $scope.$eval(tableConfig.isRowSelectable);
					} else if (angular.isFunction(tableConfig.isRowSelectable)) {
						options.isRowSelectable = tableConfig.isRowSelectable;
					}
				}
				if (tableConfig.hasOwnProperty('enableGridMenu')) {
					options.enableGridMenu = tableConfig.enableGridMenu;
				}
				if (tableConfig.hasOwnProperty('multiSelect')) {
					options.multiSelect = tableConfig.multiSelect;
				}
				if (tableConfig.hasOwnProperty('filterRowOperation')) {
					options.filterRowOperation = tableConfig.filterRowOperation;
				}
				if (tableConfig.hasOwnProperty('enableVerticalScrollbar')) {
					options.enableVerticalScrollbar = tableConfig.enableVerticalScrollbar;
				}
				if (tableConfig.hasOwnProperty('enableHorizontalScrollbar')) {
					options.enableHorizontalScrollbar = tableConfig.enableHorizontalScrollbar;
				}
				if (tableConfig.hasOwnProperty('virtualizationThreshold')) {
					options.virtualizationThreshold = tableConfig.virtualizationThreshold;
				}
				if (tableConfig.hasOwnProperty('columnVirtualizationThreshold')) {
					options.columnVirtualizationThreshold = tableConfig.columnVirtualizationThreshold;
				}
				if (tableConfig.hasOwnProperty('minRowsToShow')) {
					options.minRowsToShow = tableConfig.minRowsToShow;
				}
				if (tableConfig.hasOwnProperty('maxRowsToShow')) {
					options.maxRowsToShow = tableConfig.maxRowsToShow;
				}
				if (tableConfig.hasOwnProperty('rowHeight')) {
					options.rowHeight = tableConfig.rowHeight;
				}
				if (tableConfig.hasOwnProperty('enablePagination')) {
					options.enablePagination = tableConfig.enablePagination;
				}
				if (tableConfig.hasOwnProperty('enableAutoResize')) {
					options.enableAutoResize = tableConfig.enableAutoResize;
				}
				if (tableConfig.hasOwnProperty('enableColumnResizing')) {
					options.enableColumnResizing = tableConfig.enableColumnResizing;
				}
				if (tableConfig.hasOwnProperty('enableColumnMoving')) {
					options.enableColumnMoving = tableConfig.enableColumnMoving;
				}
				if (tableConfig.hasOwnProperty('enableRowSelection')) {
					options.enableRowSelection = tableConfig.enableRowSelection;
				}
				if (tableConfig.hasOwnProperty('enableRowHeaderSelection')) {
					options.enableRowHeaderSelection = tableConfig.enableRowHeaderSelection;
				}
				if (tableConfig.hasOwnProperty('enableSorting')) {
					options.enableSorting = tableConfig.enableSorting;
				}
				if (tableConfig.hasOwnProperty('showColumnFooter')) {
					options.showColumnFooter = tableConfig.showColumnFooter;
				}
				if (options.addRow) {
					options.showColumnFooter = true;
				}
				if (tableConfig.hasOwnProperty('selectAll')) {
					options.selectAll = tableConfig.selectAll;
				}
				if (tableConfig.hasOwnProperty('id')) {
					options.id = tableConfig.id;
				}
				return options;
			}

			function createGridOptions($scope, tableConfig, paginationChanged, rowSelectionChanged, sortChanged, apiBoundName, columnActive) {
				var defaultSort, defaultSearchCriteria, options, watcher;
				var tableSetting = storageService.getTableSetting($scope.$state.current.name + ':' + tableConfig.name);
				apiBoundName = apiBoundName || tableConfig.apiBoundName || 'gridApi';
				if(tableConfig.storageSearchCriteria) defaultSearchCriteria = storageService.getSearchCriteria($scope.$state.current.name);
				defaultSearchCriteria = defaultSearchCriteria || {
					storageSearchCriteria: tableConfig.storageSearchCriteria,
					$type : 'SearchCriteria',
					$state : $scope.$state.current.name,
					pageNo : provider.defaultGridOptions.paginationCurrentPage,
					pageSize : provider.defaultGridOptions.paginationPageSize,
					list : []
				};
				defaultSearchCriteria.pageNo = defaultSearchCriteria.pageNo || provider.defaultGridOptions.paginationCurrentPage;
				defaultSearchCriteria.totalPages = 0;
				options = angular.copy(provider.defaultGridOptions);
				// i18nService.setCurrentLang($rootScope.I18N.language);
				i18nService.setCurrentLang('en');
				// options.gridMenuTitleFilter = $translate;
				options.defaultSearchCriteria = defaultSearchCriteria;
				options.name = tableConfig.name;
				defaultSort = prepareColumnDefs($scope, tableConfig, options, tableSetting);
				options.paginationPageSize = defaultSearchCriteria.pageSize || options.paginationPageSize;
				options.defaultSearchCriteria.sortBy = defaultSearchCriteria.sortBy || defaultSort.sortBy;
				options.defaultSearchCriteria.sortDir = defaultSearchCriteria.sortDir || defaultSort.sortDir;
				options.columnDefs = tableConfig.columnDefs || [];
				if (options.enableVerticalScrollbar == uiGridConstants.scrollbars.NEVER && options.columnDefs.length > 0) {
					options.columnDefs[options.columnDefs.length - 1].pinnedRight = true;
				}
				options.columnActive = function(content) {
					if(angular.isFunction(columnActive)){
						columnActive();
					}
				};
				options.onRegisterApi = function(gridApi) {
					$scope[apiBoundName] = options['gridApi'] = gridApi;
					if (gridApi.rowEdit) {
						gridApi.rowEdit.on.saveRow($scope, function(rowEntity) {
							var defered = $q.defer();
							$scope[apiBoundName].rowEdit.setSavePromise(rowEntity, defered.promise);
							defered.resolve();
							return defered.promise;
						});
					}
					if (gridApi.pagination) {
						gridApi.pagination.on.paginationChanged($scope, function(pageNo, pageSize) {
							if (options.defaultSearchCriteria.pageNo != pageNo) {
								gridApi.grid.selection.selectAll = false;
							}
							if (angular.isFunction(paginationChanged)) {
								paginationChanged(pageNo, pageSize);
							}
						});
					}
					if (gridApi.selection) {
						
						gridApi.selection.on.rowSelectionChanged($scope, function(row, event) {
							var rows;
							if (row.grid._selectedRows) {
								if (row.isSelected) {
									addRow(row.grid, row.grid._selectedRows, row.entity);
									if(SYS_PARAMS.MULTI_PAGE_SELECT_MAX < row.grid._selectedRows.length){
										modalService.openErrorDialogs({
											'messages' : [ 'error.grid.maxselected' ]
										});
										gridApi.selection.unSelectRow(row.entity);
										return;
									}
								} else {
									removeRow(row.grid, row.grid._selectedRows, row.entity);
								}
							}
							if (angular.isFunction(rowSelectionChanged)) {
								rowSelectionChanged(row, row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows());
							}
							rows = row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows();
							if (rows.length == 1) {
								var dataType = rows[0].currentDataType || rows[0].wfTasktype;
								var dataKey = rows[0].primaryKey || rows[0].wfItemKey;
								var dataStatus = rows[0].wfStatusCode || rows[0].taskDisplayName;
								var serviceCode = rows[0].serviceCode || $rootScope.serviceCode;
								// only main grid table need call the method.
								if (dataType && dataKey) {
									if ($scope.$resolve && $scope.$resolve.dialogsModule) {
										if ($scope.$resolve.dialogsModule.enableViewAuditOrNote) {
											$rootScope.initAuditOrNoteParams(dataType, dataKey, dataStatus, serviceCode, rows[0].taskId);
										}
									} else {
										$rootScope.initAuditOrNoteParams(dataType, dataKey, dataStatus, serviceCode, rows[0].taskId);
									}
								}
							} else {
								$rootScope.removeAuditOrNoteParams();
							}
						});
						//fixed bug for multi selected
						gridApi.selection.on.rowSelectionChangedBatch($scope, function(rows, event) {
							var i = 0;
							if (rows.length > 0 && rows[0].grid._selectedRows) {
								for (i = 0; i < rows.length; i++) {
									if (rows[i].isSelected) {
										addRow(rows[i].grid, rows[i].grid._selectedRows, rows[i].entity);
										if (SYS_PARAMS.MULTI_PAGE_SELECT_MAX < rows[i].grid._selectedRows.length) {
											modalService.openErrorDialogs({
												'messages' : [ 'error.grid.maxselected' ]
											});
											break;
										}
									} else {
										removeRow(rows[i].grid, rows[i].grid._selectedRows, rows[i].entity);
									}
								}
								for (; i < rows.length; i++) {
									if (rows[i].isSelected) {
										gridApi.selection.unSelectRow(rows[i].entity);
									}
								}
							}
							if (angular.isFunction(rowSelectionChanged)) {
								angular.forEach(rows, function(row) {
									rowSelectionChanged(row, row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows());
								});
							}
						});
					}
					gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
						var sorts = [];
						angular.forEach(sortColumns, function(sortColumn, key) {
							sorts.push({
								sortBy : sortColumn.colDef.sortBy,
								direction : sortColumn.sort.direction
							});
						});
						(sortChanged || angular.noop)(sorts);
					});
					gridApi.grid.registerDataChangeCallback(function() {
						if(gridApi.grid.treeBase){
							if(gridApi.grid.treeBase.tree instanceof Array && tableConfig.expandAll){
								gridApi.treeBase.expandAllRows();
							}
						}
			        });
					gridApi.grid.registerDataChangeCallback(function(grid) {
						if (gridApi.grid._selectedRows && gridApi.grid._selectedRows.length > 0) {
							if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
								options.defaultSearchCriteria.selectAll = gridApi.grid.selection.selectAll;
							}
							angular.forEach(grid.rows, function(row) {
								if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
									gridApi.selection.selectRow(row.entity);
								} else if (containRow(gridApi.grid, gridApi.grid._selectedRows, row.entity)) {
									gridApi.selection.selectRow(row.entity);
								}
							});
						}
						if (grid.options.selectAll) {
							angular.forEach(grid.rows, function(row) {
								gridApi.selection.selectRow(row.entity);
							});
						}
						
			        }, [uiGridConstants.dataChange.ROW]);
					watcher = $scope.$watch(function() {
						return options.multiSelect && options.multiPageSelect;
					}, function(multiPageSelect) {
						if (multiPageSelect == true) {
							gridApi.grid._selectedRows = gridApi.grid._selectedRows || [];
						} else {
							delete gridApi.grid._selectedRows;
						}
					});
					if (gridApi.colMovable && gridApi.colMovable.raise) {
						gridApi.colMovable.raise.columnPositionChanged = function (colDef, originalPosition, newPosition) {
							var order = [];
							if(gridApi.grid.moveColumns && gridApi.grid.moveColumns.orderCache){
								angular.forEach(gridApi.grid.moveColumns.orderCache, function(orderCache){
									order.push(orderCache.colDef.field);
								});
							}
							storageService.saveTableSetting($scope.$state.current.name + ':' + gridApi.grid.options.name, {
								order : order,
							});
						};
					}
					$scope.$on('$destroy', function() {
						watcher();
					});
					$scope.$on('ADD_ROWS', function($event, rows) {
						$event.preventDefault();
						$event.stopPropagation();
					});
					$scope.$on('REMOVE_ROWS', function($event, rows) {
						if (gridApi.grid._selectedRows) {
							if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
								gridApi.grid._selectedRows.splice(0, gridApi.grid._selectedRows.length);
							} else {
								angular.forEach(gridApi.grid._selectedRows, function(rowEntity) {
									removeRow(gridApi.grid, gridApi.grid._selectedRows, rowEntity);
								});
							}
						}
						$event.preventDefault();
						$event.stopPropagation();
					});
				};
				if (tableConfig.hasOwnProperty('enableRowHeaderSelection')) {
					options.enableRowHeaderSelection = tableConfig.enableRowHeaderSelection;
				}
				options.enableOperation = tableConfig.enableOperation;
				options.enableOperationRemoveSelected = tableConfig.enableOperationRemoveSelected;
				options.addRow = tableConfig.addRow;
				options.removeSelectedRows = tableConfig.removeSelectedRows;
				options.removeAllRows = tableConfig.removeAllRows;
				options.viewRow = tableConfig.viewRow;
				options.editRow = tableConfig.editRow;
				options.addSubRow = tableConfig.addSubRow;
				options.removeRow = tableConfig.removeRow;
				options.data = tableConfig.model;
				options.verifyData = tableConfig.verifyModel;
				options.validatorConfig = tableConfig.validatorConfig;
				options.moreProcess = tableConfig.moreProcess;
				options.moreProcessByEol = tableConfig.moreProcessByEol;
				if (tableConfig.hasOwnProperty('isRowSelectable')) {
					if (angular.isString(tableConfig.isRowSelectable)) {
						options.isRowSelectable = $scope.$eval(tableConfig.isRowSelectable);
					} else if (angular.isFunction(tableConfig.isRowSelectable)) {
						options.isRowSelectable = tableConfig.isRowSelectable;
					}
				}
				if (tableConfig.hasOwnProperty('enableGridMenu')) {
					options.enableGridMenu = tableConfig.enableGridMenu;
				}
				if (tableConfig.hasOwnProperty('multiSelect')) {
					options.multiSelect = tableConfig.multiSelect;
				}
				if (tableConfig.hasOwnProperty('filterRowOperation')) {
					options.filterRowOperation = tableConfig.filterRowOperation;
				}
				if (tableConfig.hasOwnProperty('enablePaginationControls')) {
					options.enablePaginationControls = tableConfig.enablePaginationControls;
				}
				if (tableConfig.hasOwnProperty('enableVerticalScrollbar')) {
					options.enableVerticalScrollbar = tableConfig.enableVerticalScrollbar;
				}
				if (tableConfig.hasOwnProperty('enableHorizontalScrollbar')) {
					options.enableHorizontalScrollbar = tableConfig.enableHorizontalScrollbar;
				}
				if (tableConfig.hasOwnProperty('virtualizationThreshold')) {
					options.virtualizationThreshold = tableConfig.virtualizationThreshold;
				}
				if (tableConfig.hasOwnProperty('columnVirtualizationThreshold')) {
					options.columnVirtualizationThreshold = tableConfig.columnVirtualizationThreshold;
				}
				if (tableConfig.hasOwnProperty('minRowsToShow')) {
					options.minRowsToShow = tableConfig.minRowsToShow;
				}
				if (tableConfig.hasOwnProperty('maxRowsToShow')) {
					options.maxRowsToShow = tableConfig.maxRowsToShow;
				}
				if (tableConfig.hasOwnProperty('rowHeight')) {
					options.rowHeight = tableConfig.rowHeight;
				}
				if (tableConfig.hasOwnProperty('enablePagination')) {
					options.enablePagination = tableConfig.enablePagination;
				}
				if (tableConfig.hasOwnProperty('enableAutoResize')) {
					options.enableAutoResize = tableConfig.enableAutoResize;
				}
				if (tableConfig.hasOwnProperty('enableColumnResizing')) {
					options.enableColumnResizing = tableConfig.enableColumnResizing;
				}
				if (tableConfig.hasOwnProperty('enableColumnMoving')) {
					options.enableColumnMoving = tableConfig.enableColumnMoving;
				}
				if (tableConfig.hasOwnProperty('enableRowSelection')) {
					options.enableRowSelection = tableConfig.enableRowSelection;
				}
				if (tableConfig.hasOwnProperty('enableRowHeaderSelection')) {
					options.enableRowHeaderSelection = tableConfig.enableRowHeaderSelection;
				}
				if (tableConfig.hasOwnProperty('enableSorting')) {
					options.enableSorting = tableConfig.enableSorting;
				}
				if (tableConfig.hasOwnProperty('selectAll')) {
					options.selectAll = tableConfig.selectAll;
				}
				if (tableConfig.hasOwnProperty('showColumnFooter')) {
					options.showColumnFooter = tableConfig.showColumnFooter;
				}
				if (options.addRow) {
					options.showColumnFooter = true;
				}
				if (tableConfig.hasOwnProperty('id')) {
					options.id = tableConfig.id;
				}
				return options;
			}

			function prepareColumnDefs($scope, tableConfig, options, tableSetting) {
				var newColDefs = [], defaultSort = {}, i, watcher;
				options.appScopeProvider = options.appScope = $scope;
				angular.forEach(tableConfig.columnDefs, function(column, key) {
					//set validatorConfig.
					column.validatorConfig = tableConfig.validatorConfig;
					column.sortDirectionCycle = [uiGridConstants.ASC, uiGridConstants.DESC];
					if (column.sort) {
						defaultSort.sortBy = column.sortBy;
						defaultSort.sortDir = column.sort.direction;
					} else {
						column.sort = {};
					}
					if (column.type && options.type != 'label' && options.type != 'image') {
						column.cellTemplate = column.template || column.cellTemplate || provider.fsGridTemplate;
					} else if (column.template) {
						column.cellTemplate = column.template;
					}
					column.displayName = column.displayName || column.label;
					delete column.label;
					column.field = column.field || column.model;
					column.cellFilter = column.cellFilter || column.filter;
					/*
					 * column.cellTooltip = function() { return $scope.fsGridConfig.tooltipMessage; };
					 */
					if (column.displayName) {
						$translate(column.displayName).then(function(displayName) {
							column.displayName = displayName;
						}, angular.noop);
					}
					if (angular.isString(column.options)) {
						watcher = $scope.$watch(column.options, function(newValue, oldValue) {
							column.options = newValue;
						});
						$scope.$on('$destroy', function() {
							watcher();
						});
					} else {
						column.options = column.options;
					}
					if(!options.displayStyle){
						if (angular.isNumber(column.width) || (angular.isString(column.width) && column.width.match(/^(\d+)[%]$/))) {
							options.displayStyle = 'normal';
						} else if (angular.isNumber(column.minWidth) || (angular.isString(column.minWidth) && column.minWidth.match(/^(\d+)$/))) {
							options.displayStyle = 'normal';
						} else {
							options.displayStyle = 'all';
						}
					}
					if (tableSetting && tableSetting.visible) {
						column.visible = tableSetting.visible[column.field];
					}
					if (tableSetting && tableSetting.width && tableSetting.width[options.displayStyle] && tableSetting.width[options.displayStyle][column.field]) {
						column.width = tableSetting.width[options.displayStyle][column.field].width;
						column.minWidth = tableSetting.width[options.displayStyle][column.field].minWidth;
						column.maxWidth = tableSetting.width[options.displayStyle][column.field].maxWidth;
					}
				});
				if (tableSetting && tableSetting.order) {
					angular.forEach(tableSetting.order, function(columnField) {
						for (i = 0; i < tableConfig.columnDefs.length; i++) {
							if (columnField == tableConfig.columnDefs[i].field) {
								newColDefs.push(tableConfig.columnDefs[i]);
								break;
							}
						}
					});
					tableConfig.columnDefs = newColDefs;
				}
				return defaultSort;
			}
			
			function updateGridOptions(searchCriteria, gridOptions) {
				var columnDefs = gridOptions.columnDefs;
				var i, columns = gridOptions.gridApi ? gridOptions.gridApi.grid.renderContainers.body.renderedColumns : undefined;
				gridOptions.totalItems = searchCriteria.totalRows;
				if (searchCriteria.sortBy && searchCriteria.sortDir) {
					angular.forEach(columnDefs, function(column, key) {
						if (column.sortBy == searchCriteria.sortBy) {
							column.sort = column.sort || {};
							column.sort.direction = searchCriteria.sortDir;
							for(i = 0; columns && i < columns.length; i++){
								if (columns[i].field == column.field) {
									columns[i].sort = columns[i].sort || {};
									columns[i].sort.direction = searchCriteria.sortDir;
									break;
								}
							}
						} else if (column.sort) {
							delete column.sort.direction;
							for(i = 0; columns && i < columns.length; i++){
								if (columns[i].field == column.field) {
									delete columns[i].sort.direction;
									break;
								}
							}
						}
					});
				}
				if(searchCriteria.pageNo) {
					gridOptions.paginationCurrentPage = searchCriteria.pageNo;
				} 
				if(searchCriteria.pageSize) {
					gridOptions.paginationPageSize = searchCriteria.pageSize;
				} 
			}
			
			function containRow(grid, dstRows, rowEntity) {
				var i = 0;
				for (i = 0; i < dstRows.length; i++) {
					if (grid.options.rowEquality(dstRows[i], rowEntity) || (dstRows[i].primaryKey == rowEntity.primaryKey && rowEntity.primaryKey != undefined)) {
						dstRows[i] = rowEntity;
						return true;
					}
				}
				return false;
			}
			
			function addRow(grid, dstRows, rowEntity) {
				var i = 0;
				if (grid.selection.selectAll && supportMultiPageSelectAll) {
					return;
				}
				if (dstRows.length == 0) {
					dstRows.push(rowEntity);
					return;
				}
				for (i = 0; i < dstRows.length; i++) {
					if (grid.options.rowEquality(dstRows[i], rowEntity) || (dstRows[i].primaryKey == rowEntity.primaryKey && rowEntity.primaryKey != undefined)) {
						break;
					}
				}
				if (i >= dstRows.length) {
					dstRows.push(rowEntity);
				}
			}

			function removeRow(grid, dstRows, rowEntity) {
				var i = 0;
				if (grid.selection.selectAll && supportMultiPageSelectAll) {
					dstRows.splice(0, dstRows.length);
					return;
				}
				for (i = 0; i < dstRows.length; i++) {
					if (grid.options.rowEquality(dstRows[i], rowEntity) || (dstRows[i].primaryKey == rowEntity.primaryKey && rowEntity.primaryKey != undefined)) {
						dstRows.splice(i, 1);
						return;
					}
				}
			}

			return {
				createGridOptions : createGridOptions,
				createInnerGridOptions : createInnerGridOptions,
				updateGridOptions : updateGridOptions,
				removeSelectedRows : removeSelectedRows,
				removeRows : removeRows
			};
		}
	}

})(angular);
